"""--------------------------------------------------------------------------------------------------
Filename:   plotpanel.py
Author:     Chris Chester, adapted from Ben Han (uha10@uclive.ac.nz)
Date:       17 May 2010
Description:
    Module containing GUI elements from which the main plot window is composed.
    
Previous authors of CLASS PlotPanel: Edward Abraham, John Bender, CWRU, 10 Sep 08
Modified by:    Chris Chester (29th August 2012)
Modified by:    Ben Han (27 April 2010)

Original comments----------------------------------------------------------
New version based on the original by Edward Abraham, incorporating some
forum discussion, minor bugfixes, and working for Python 2.5.2,
wxPython 2.8.7.1, and Matplotlib 0.98.3.
I haven't found an advantage to using the NoRepaintCanvas, so it's removed.
John Bender, CWRU, 10 Sep 08
---------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------"""

import wx

#===============================================================================
# CLASS: MyPlotPanel( PlotPanel(wx.Panel) )
#    Main plotting class. Uses PlotPanel class (derived from wx.Panel)
#===============================================================================
class PlotPanel(wx.Panel):
    """ Live updating plot for feedback.
        self.target - target used in the plot, either 2D line object or Rectangle object
    """
    
    def __init__( self, parent, color=None, dpi=80, **kwargs ):
        from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg
        from matplotlib.figure import Figure
        # initialize Panel
        if 'id' not in kwargs.keys():
            kwargs['id'] = wx.ID_ANY
        if 'style' not in kwargs.keys():
            kwargs['style'] = wx.NO_FULL_REPAINT_ON_RESIZE
        wx.Panel.__init__( self, parent, **kwargs )
        self.SetSize((800,600))

        # initialize matplotlib stuff
        self.figure = Figure( None, dpi )
        self.canvas = FigureCanvasWxAgg( self, -1, self.figure )
        self.SetColor( color )

        self._resizeflag = False

        self.Bind(wx.EVT_IDLE, self._onIdle)
        self.Bind(wx.EVT_SIZE, self._onSize)
        
        self.parent = parent
        
    def SetColor( self, rgbtuple=None ):
        """Set figure and canvas colours to be the same."""
        if rgbtuple is None:
            rgbtuple = wx.SystemSettings.GetColour( wx.SYS_COLOUR_BTNFACE ).Get()
        clr = [c/255. for c in rgbtuple]
        self.figure.set_facecolor( clr )
        self.figure.set_edgecolor( clr )
        self.canvas.SetBackgroundColour( wx.Colour( *rgbtuple ) )

    def _onSize( self, event ):
        self._resizeflag = True

    def _onIdle( self, evt ):
        if self._resizeflag:
            self._resizeflag = False
            self._SetSize()

    def _SetSize( self ):
        pixels = self.parent.GetClientSizeTuple()
        button_panel_size = self.parent.GetParent().plotctrl.minsize
        w = pixels[0]
        h = pixels[1] - button_panel_size[1]
        pixels = (w, h)
        self.SetSize( pixels )
        self.canvas.SetSize( pixels )
        self.figure.set_size_inches( float( pixels[0] )/self.figure.get_dpi(),
                                     float( pixels[1] )/self.figure.get_dpi() )

        
#===============================================================================
# CLASS: PlotControl(wx.Panel)
#    Container class for the control buttons in the plot window
#===============================================================================
class PlotControl(wx.Panel):
    def __init__(self, parent, id, app):
        wx.Panel.__init__(self, parent, id)
        self.app = app
        # Create buttons
        self.start_sess_button = wx.Button(self, -1, "Start", )
        self.pause_button = wx.Button(self, -1, "Pause")
        self.save_button = wx.Button(self, -1, "Save and exit")
        self.menu_button = wx.Button(self, -1, "Exit to menu")

        # Create check boxes
        self.cb_grid = wx.CheckBox(self, -1, "Grid")
        
        self.__set_properties()
        self.__do_layout()
        
        # Sets handlers
        self.Bind(wx.EVT_BUTTON, self.app.phdls.start_sess_button, self.start_sess_button)
        self.Bind(wx.EVT_BUTTON, self.app.phdls.pause, self.pause_button)
        self.Bind(wx.EVT_BUTTON, self.app.phdls.save_exit, self.save_button)
        self.Bind(wx.EVT_BUTTON, self.app.phdls.exit_plot, self.menu_button)

        self.Bind(wx.EVT_CHECKBOX, self.on_cb_grid, self.cb_grid)
        
    def __set_properties(self):
        self.start_sess_button.Enable(False)
        self.start_sess_button.SetMinSize((70, 30))
        self.pause_button.Enable(False)
        self.pause_button.SetMinSize((70, 30))
        self.save_button.Enable(False)
        self.save_button.SetMinSize((100, 30))
        self.menu_button.SetMinSize((100, 30))
        
        cfg = self.app.cfg
        
        self.cb_grid.SetValue(cfg.default_grid)

        
    def __do_layout(self):
        DEFAULT_GAP = 5
        
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        # Add buttons to sizer
        box_control = wx.StaticBox(self, -1, "Control")
        sizer_control = wx.StaticBoxSizer(box_control, wx.HORIZONTAL)
        sizer_control.Add(self.start_sess_button, 0, wx.ALL | wx.CENTRE, DEFAULT_GAP)
        sizer_control.Add(self.pause_button, 0, wx.ALL | wx.CENTRE, DEFAULT_GAP)
        sizer_control.Add(self.save_button, 0, wx.ALL | wx.CENTRE, DEFAULT_GAP)
        sizer_control.Add(self.menu_button, 0, wx.ALL | wx.CENTRE, DEFAULT_GAP)
        
        # Add checkboxes to sizer
        GRID_SIZE = 2
        DIST_BETWN_BOX = 10
        
        box_checkBox = wx.StaticBox(self, -1, "Plot options")
        sizer_checkBox = wx.GridSizer(GRID_SIZE,GRID_SIZE,DIST_BETWN_BOX,DIST_BETWN_BOX)
        
        sizer_checkBox.Add(self.cb_grid, 0, wx.ALL | wx.CENTRE, DEFAULT_GAP)
        
        sizer_boxes = wx.StaticBoxSizer(box_checkBox, wx.VERTICAL)
        sizer_boxes.Add(sizer_checkBox)

                
        # Add sizers to main sizer
        sizer.Add(sizer_control, 0, wx.ALL | wx.EXPAND, 20)
        sizer.Add(sizer_boxes, 1, wx.ALL | wx.EXPAND, 20)

        ms = sizer.GetMinSize()             # to be used by PlotPanel._SetSize()
        self.minsize = (ms[0], ms[1]+10)    # change this implementation to a general form to take into account borders
        self.SetSizer(sizer)
        
    def on_upper_spin(self, event):
        cfg = self.app.cfg
        cfg._upper_limit = self.upper_limit_spin.GetValue()/100.0
        range_max = [cfg._trial_len - cfg._x_margin, cfg._upper_limit*self.app.sess_status.baseline]
        self.app.plot.tfactory.set_range_max(range_max)
        
    def on_lower_spin(self, event):
        cfg = self.app.cfg
        cfg._lower_limit = self.lower_limit_spin.GetValue()/100.0
        range_min = [cfg._x_margin, cfg._lower_limit*self.app.sess_status.baseline]
        self.app.plot.tfactory.set_range_min(range_min)
        
    def on_cb_grid(self, event):
        self.app.ctrl.chkbx_ctrl.cb_grid.SetValue(self.cb_grid.GetValue())
        self.app.plot.draw_grid(self.cb_grid.GetValue())

        

# End of plotpanel.py